/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor. Adios!
 */

package diagramtodbfx;

import GenerateDB.ScriptMongo;
import GenerateDB.ScriptSQL;
import JDBC.UtilsJDBC;
import Models.Model;
import Models.Models;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.FileChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;

/**
 *
 * @author Nico
 */
public class DiagramToDBFX extends Application {
    
    private TableView<ModelFX> table = new TableView<>();
    ChoiceBox opciones = null;
    private ObservableList<ModelFX> data = FXCollections.observableArrayList();
    private Models esquemas = new Models();
    
    private void addModelstoData(ArrayList<Model> esquemas){
        for(int i=0; i<esquemas.size(); i++){
            data.add(new ModelFX(esquemas.get(i).getNombre(), esquemas.get(i).getFecha()));
        }
    }
    
    private void addEsquema(File file) throws IOException{
        esquemas.addModel(file.getPath());
        data.add(new ModelFX(
            esquemas.getModels().get(esquemas.getModels().size()-1).getNombre(),
            esquemas.getModels().get(esquemas.getModels().size()-1).getFecha())
        );        
    }
    
   
    
    private  HashMap<String, ArrayList<String> > preprocesamiento(String esquema, Stage primaryStage){
        UtilsJDBC u = new UtilsJDBC();        
        
        /********* Elección de claves primarias *******/
        HashMap<String, ArrayList<String> > candidatas = u.getEntityKeys(esquema);
        HashMap<String, String > primarias = new HashMap<>();
        Set<String> s = candidatas.keySet();
        Iterator<String> it = s.iterator();
        while(it.hasNext()){
            String entidad = it.next();
            if(candidatas.get(entidad).size() > 1){
                
                Stage myDialog = new MyDialog(primaryStage, candidatas.get(entidad),entidad);
                myDialog.sizeToScene();
                myDialog.showAndWait();
                
                
                System.out.println("Item seleccionado: " + this.opciones.getSelectionModel().getSelectedIndex());
                int opcion = this.opciones.getSelectionModel().getSelectedIndex()+1;
                if(opcion > 0 && opcion < candidatas.get(entidad).size()+1)
                    primarias.put(entidad, candidatas.get(entidad).get(opcion-1));
                else
                    return null;
            }
            else{
                primarias.put(entidad, candidatas.get(entidad).get(0));
            }
        }
        
        HashMap<String, ArrayList<String> >  allprimarys =  u.getEntityPrimariKeys(esquema, primarias);
        u.disconnect();

        
        /********* Elección del tipo de especialización *******/
        
        
        return allprimarys;
    }

    @Override
    public void start(final Stage stage) throws Exception {
        //Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
        //Scene scene = new Scene(root);
        

        Scene scene = new Scene(new Group());
        stage.setTitle("DiagramToDB");
        stage.setWidth(1024);
        stage.setHeight(768);
 
        final Label label = new Label("Seleccione un esquema...");
        label.setScaleX(2);
        table.setEditable(true);
 
        TableColumn firstNameCol = new TableColumn("Esquema");
        firstNameCol.setMinWidth(507);
        firstNameCol.setCellValueFactory(
                new PropertyValueFactory<ModelFX, String>("nombre"));
 
        TableColumn lastNameCol = new TableColumn("Fecha de Creación");
        lastNameCol.setMinWidth(507);
        lastNameCol.setCellValueFactory(
                new PropertyValueFactory<ModelFX, String>("fecha"));
 
        addModelstoData(esquemas.getModels());
        table.setItems(data);
        table.getColumns().addAll(firstNameCol, lastNameCol);
 
        /** Botón Añadir */
        final VBox vbox = new VBox();
        final HBox hbox = new HBox();
        final HBox supopt = new HBox();
        final FileChooser fileChooser = new FileChooser();
        final Button addButton = new Button("Añadir Esquema");
        final Button statsButton = new Button("Generar BD Mongo");
        final Button generateButton = new Button("Script SQL");
        final Text errors = new Text();
        final Text mongotextArea = new Text("Fichero de colecciones Mongo que recogen información de interés de los esquemas");
        final Text sqltextArea = new Text("Fichero SQL de creación de tablas del esquema seleccionado");
        
        final ToggleGroup group = new ToggleGroup();

        
        /* Añadir esquema */
        addButton.setOnAction(
            new EventHandler<ActionEvent>() {
                @Override
                public void handle(final ActionEvent e) {
                    File file = fileChooser.showOpenDialog(stage);
                 
                    if (file != null) {
                        try {
                            addEsquema(file);
                        } catch (IOException ex) {
                            Logger.getLogger(DiagramToDBFX.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }
        });
        
        
      
        
        /* Generar esquema */
        generateButton.setOnAction(
            new EventHandler<ActionEvent>() {
                @Override
                public void handle(final ActionEvent e) {
                    if(table.getSelectionModel().getSelectedItems().size() == 1){//Si se ha seleccionado alguno
                        HashMap<String, ArrayList<String> >  allprimarys = preprocesamiento(table.getSelectionModel().getSelectedItems().get(0).getNombre(),stage); 
                        if(allprimarys != null){
                            ScriptSQL scriptsql = new ScriptSQL(table.getSelectionModel().getSelectedItems().get(0).getNombre(), allprimarys);
                            File file = fileChooser.showSaveDialog(stage);
                            file.getAbsolutePath();
                            if(file.getAbsoluteFile().getAbsolutePath() != null){
                                scriptsql.generate(table.getSelectionModel().getSelectedItems().get(0).getNombre(), file.getAbsolutePath());
                                errors.setText("Se ha generado con éxito! :)");
                            }
                            else{
                                errors.setText("¡¡¡¡¡¡¡ ATENCION !!!!!! -> No se ha especificado correctamente el nombre o ruta del archivo");
                            }                            
                        }
                        else{
                                errors.setText("¡¡¡¡¡¡¡ ATENCION !!!!!! -> No se ha especificado ninguna clave");
                        }

                    }
                    else{
                        errors.setText("¡¡¡¡¡¡¡ ATENCION !!!!!! -> Se debe seleccionar un esquema para generar el Script");
                    }
                }
        });   
        
        /* Generar Mongo */
        statsButton.setOnAction(
            new EventHandler<ActionEvent>() {
                @Override
                public void handle(final ActionEvent e) {
                    ScriptMongo scriptmongo = new ScriptMongo();
                    File file = fileChooser.showSaveDialog(stage);
                    file.getAbsolutePath();
                    scriptmongo.generate(file.getAbsolutePath());
                }
        });    
          
                
                
        vbox.setSpacing(30);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        
        supopt.setSpacing(20);
        supopt.getChildren().addAll(addButton,statsButton, mongotextArea);
        
        hbox.setSpacing(20);
        hbox.getChildren().addAll(generateButton,sqltextArea);
        
        vbox.getChildren().addAll(supopt,table,errors,hbox);
        
 
        
        ((Group) scene.getRoot()).getChildren().addAll(vbox);
 
        stage.setScene(scene);
        stage.show();

    }
    
    class MyDialog extends Stage {

        public MyDialog(Stage owner, ArrayList<String> claves, String entidad) {
            super();
            initOwner(owner);
            setTitle("Claves Candidatas");
            initModality(Modality.APPLICATION_MODAL);
            Group root = new Group();
            Scene scene = new Scene(root, 450, 150, Color.WHITE);
            setScene(scene);

            GridPane gridpane = new GridPane();
            gridpane.setPadding(new Insets(5));
            gridpane.setHgap(5);
            gridpane.setVgap(5);

            Label clave = new Label("Entidad "+entidad+" tiene varias claves. Elija una: ");
            gridpane.add(clave, 0, 1);

            opciones = new ChoiceBox(FXCollections.observableArrayList(claves));
            gridpane.add(opciones, 1, 1);
            
            Button aceptar = new Button("Aceptar");
            aceptar.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    close();
                }
            });
            gridpane.add(aceptar, 1, 3);
            GridPane.setHalignment(aceptar, HPos.RIGHT);
            root.getChildren().add(gridpane);
        }
    }    

    /**
     * The main() method is ignored in correctly deployed JavaFX application.
     * main() serves only as fallback in case the application can not be
     * launched through deployment artifacts, e.g., in IDEs with limited FX
     * support. NetBeans ignores main().
     *
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
    
    
    public static class ModelFX {
 
        private final SimpleStringProperty nombre;
        private final SimpleStringProperty fecha;
 
        private ModelFX(String nombre, String fecha) {
            this.nombre = new SimpleStringProperty(nombre);
            this.fecha = new SimpleStringProperty(fecha);
        }
 
        public String getNombre() {
            return nombre.get();
        }
 
        public void setNombre(String nombre) {
            this.nombre.set(nombre);
        }
 
        public String getFecha() {
            return fecha.get();
        }
 
        public void setFecha(String fecha) {
            this.fecha.set(fecha);
        } 
    }

}
